package com.company.workflow.service.impl;

import com.company.workflow.model.vo.ProcessInstanceVO;
import com.company.workflow.model.vo.ProcessStatisticsVO;
import com.company.workflow.service.ProcessMonitorService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ProcessMonitorServiceImpl implements ProcessMonitorService {

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private HistoryService historyService;

    @Override
    public List<ProcessInstanceVO> listInstances(String processDefinitionKey, String status) {
        List<ProcessInstanceVO> result = new ArrayList<>();
        
        // 查询运行中的实例
        if (status == null || "active".equals(status)) {
            List<ProcessInstance> runningInstances = runtimeService.createProcessInstanceQuery()
                    .processDefinitionKey(processDefinitionKey)
                    .active()
                    .list();
            
            result.addAll(runningInstances.stream()
                    .map(this::convertToVO)
                    .collect(Collectors.toList()));
        }
        
        // 查询历史实例
        if (status == null || "completed".equals(status)) {
            List<HistoricProcessInstance> historicInstances = historyService.createHistoricProcessInstanceQuery()
                    .processDefinitionKey(processDefinitionKey)
                    .finished()
                    .list();
            
            result.addAll(historicInstances.stream()
                    .map(this::convertToVO)
                    .collect(Collectors.toList()));
        }
        
        return result;
    }

    @Override
    public ProcessStatisticsVO getStatistics() {
        ProcessStatisticsVO statistics = new ProcessStatisticsVO();
        
        // 统计总实例数
        long totalInstances = historyService.createHistoricProcessInstanceQuery().count();
        statistics.setTotalInstances(totalInstances);
        
        // 统计活动实例数
        long activeInstances = runtimeService.createProcessInstanceQuery().active().count();
        statistics.setActiveInstances(activeInstances);
        
        // 统计完成实例数
        long completedInstances = historyService.createHistoricProcessInstanceQuery().finished().count();
        statistics.setCompletedInstances(completedInstances);
        
        // 统计挂起实例数
        long suspendedInstances = runtimeService.createProcessInstanceQuery().suspended().count();
        statistics.setSuspendedInstances(suspendedInstances);
        
        // 计算平均持续时间
        List<HistoricProcessInstance> completedProcesses = historyService.createHistoricProcessInstanceQuery()
                .finished()
                .list();
        double averageDuration = completedProcesses.stream()
                .mapToLong(HistoricProcessInstance::getDurationInMillis)
                .average()
                .orElse(0.0);
        statistics.setAverageDuration(averageDuration);
        
        // 按流程统计实例数
        Map<String, Long> instancesByProcess = completedProcesses.stream()
                .collect(Collectors.groupingBy(
                        HistoricProcessInstance::getProcessDefinitionKey,
                        Collectors.counting()));
        statistics.setInstancesByProcess(instancesByProcess);
        
        return statistics;
    }

    @Override
    public Map<String, Object> getTrend(String timeRange) {
        Map<String, Object> result = new HashMap<>();
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startTime;
        
        // 根据时间范围确定开始时间
        switch (timeRange) {
            case "week":
                startTime = now.minusWeeks(1);
                break;
            case "month":
                startTime = now.minusMonths(1);
                break;
            case "year":
                startTime = now.minusYears(1);
                break;
            default:
                startTime = now.minusDays(7);
        }
        
        // 查询指定时间范围内的流程实例
        List<HistoricProcessInstance> instances = historyService.createHistoricProcessInstanceQuery()
                .startedAfter(Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()))
                .orderByProcessInstanceStartTime().asc()
                .list();
        
        // 按天统计流程实例数
        Map<String, Long> dailyCount = instances.stream()
                .collect(Collectors.groupingBy(
                        instance -> instance.getStartTime().toInstant()
                                .atZone(ZoneId.systemDefault())
                                .toLocalDate()
                                .toString(),
                        Collectors.counting()));
        
        result.put("dailyCount", dailyCount);
        return result;
    }

    @Override
    public void suspendInstance(String processInstanceId) {
        runtimeService.suspendProcessInstanceById(processInstanceId);
    }

    @Override
    public void activateInstance(String processInstanceId) {
        runtimeService.activateProcessInstanceById(processInstanceId);
    }

    private ProcessInstanceVO convertToVO(ProcessInstance instance) {
        ProcessInstanceVO vo = new ProcessInstanceVO();
        vo.setId(instance.getId());
        vo.setProcessDefinitionId(instance.getProcessDefinitionId());
        vo.setProcessDefinitionKey(instance.getProcessDefinitionKey());
        vo.setProcessDefinitionName(instance.getProcessDefinitionName());
        vo.setBusinessKey(instance.getBusinessKey());
        vo.setStartUserId(instance.getStartUserId());
        vo.setStartTime(LocalDateTime.ofInstant(instance.getStartTime().toInstant(), ZoneId.systemDefault()));
        vo.setStatus(instance.isSuspended() ? "suspended" : "active");
        return vo;
    }

    private ProcessInstanceVO convertToVO(HistoricProcessInstance instance) {
        ProcessInstanceVO vo = new ProcessInstanceVO();
        vo.setId(instance.getId());
        vo.setProcessDefinitionId(instance.getProcessDefinitionId());
        vo.setProcessDefinitionKey(instance.getProcessDefinitionKey());
        vo.setProcessDefinitionName(instance.getProcessDefinitionName());
        vo.setBusinessKey(instance.getBusinessKey());
        vo.setStartUserId(instance.getStartUserId());
        vo.setStartTime(LocalDateTime.ofInstant(instance.getStartTime().toInstant(), ZoneId.systemDefault()));
        if (instance.getEndTime() != null) {
            vo.setEndTime(LocalDateTime.ofInstant(instance.getEndTime().toInstant(), ZoneId.systemDefault()));
            vo.setStatus("completed");
            vo.setDuration(instance.getDurationInMillis());
        }
        return vo;
    }
} 